package com.deng.framework.beans.factory.support;

import com.deng.framework.beans.BeansException;
import com.deng.framework.beans.factory.ConfigurableListableBeanFactory;
import com.deng.framework.beans.factory.config.BeanDefinition;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 真正用来实现IBean注册的类，继承了AbstractAutowireCapableBeanFactory和BeanDefinitionRegistry
 * tips:补充了implements ConfigurableListableBeanFactory，这个是用来做Bean扩展相关的实现的
 */
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry, ConfigurableListableBeanFactory {
    //Bean注册链表
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    //注册
    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        beanDefinitionMap.put(beanName,beanDefinition);
    }

    @Override
    public boolean containsBeanDefinition(String beanName) {
        return beanDefinitionMap.containsKey(beanName);
    }


    //获取
    @Override
    public BeanDefinition getBeanDefinition(String beanName) throws BeansException {
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(beanDefinition == null) throw new BeansException("No bean named '" + beanName + "' is defined");
        return beanDefinition;
    }

    /**
     * Bean自定义扩展的相关实现
     */
    //获取所有bean的类型，这是个含重要的函数，在很多类中都有使用
    //值得注意的是，这里获取的是一个<beanName,bean实例化（及对应的class对象）>的map，所以获取到的bean肯定是经过了bean的生命周期的
    @Override
    public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
        Map<String, T> result = new HashMap<>();
        beanDefinitionMap.forEach((beanName, beanDefinition) -> {
            Class beanClass = beanDefinition.getBeanClass();
            //isAssignableFrom是Java中的一个方法，用于判断一个类或接口是否与另一个类或接口相同，或者是否是其超类或超接口。
            //例如，如果有两个类A和B，A是B的父类，则可以使用A.isAssignableFrom(B)来判断B是否是A的子类。
            if (type.isAssignableFrom(beanClass)) {
                result.put(beanName, (T) getBean(beanName));
            }
        });
        return result;
    }

    @Override
    public String[] getBeanDefinitionNames() {
        return beanDefinitionMap.keySet().toArray(new String[0]);
    }

    //通过遍历+getBean来实现提前实例化
    @Override
    public void preInstantiateSingletons() throws BeansException {
        beanDefinitionMap.keySet().forEach(this::getBean);
    }

    /**
     * 注解模块时的补充函数
     */
    @Override
    public <T> T getBean(Class<T> requiredType) throws BeansException {
        List<String> beanNames = new ArrayList<>();
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            Class beanClass = entry.getValue().getBeanClass();
            if (requiredType.isAssignableFrom(beanClass)) {
                beanNames.add(entry.getKey());
            }
        }
        if (1 == beanNames.size()) {
            return getBean(beanNames.get(0), requiredType);
        }

        throw new BeansException(requiredType + "expected single bean but found " + beanNames.size() + ": " + beanNames);
    }
}
